#!/usr/bin/env python

class Reader:
    def char    (self): raise AbstractMethodError(self, self.char)
    def nextchar(self): raise AbstractMethodError(self, self.nextchar())

class String(Reader):
    def __init__(self, string):
        self.len    = len(string)
        self.string = string
        self.pos    = 0
        self.line   = 1
        self.curr   = self.setcurr()

    def nextchar(self):
        if self.curr == "\n": self.line += 1
        self.pos += 1
        return self.setcurr()

    def setcurr(self):
        if   self.pos <  self.len: self.curr = self.string[self.pos]
        else                     : self.curr = ""
        return self.curr

    def __str__(self): return str(self.pos) + ":" + str(self.string)

    def point(self):
        linestart = self.string.rfind("\n", 0, self.pos) + 1
        lineend   = self.string.find("\n", self.pos)
        return "Line: " + str(self.line) + self.filename() + "\n" + self.string[linestart:lineend] + "\n" + "^".rjust(self.pos - linestart)

    def filename(self): return " - "
    def char(self): return self.curr

class FDBuffer(String):
    def __init__(self, fd): String.__init__(self, fd.read())

class FileBuffer(String):
    def __init__(self, filename):
        fd = open(filename)
        FDBuffer.__init__(self, fd)
        fd.close()
